有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java类的“set”方法是否应该返回“void”或“boolean”?

所以我在设计一个类的时候经常遇到这个问题:

class foo {

    private Bar bar;

    public foo(Bar bar) {
        this.bar = bar;
    }

    public Bar getBar() {
        return bar;
    }

    public void setBar(Bar bar) {
        this.bar = bar;
    }
}

到目前为止还不错,对吧?但是我想“我怎么知道用户会传递一个可接受的bar对象呢

    private bool validateBar(Bar bar) {
        return amIgood(bar);
    }

当然,我需要把它和setBar函数放在一起,如下所示:

    public bool setBar(Bar bar) {
        if (validateBar(bar)) {
            this.bar = bar;
            return true;
        }
        else
            return false;
    }

如果这就是我需要做的,那么我也必须包含在构造函数中,对吗?除了构造函数没有返回foo对象以外的任何对象的选项,所以我尝试并考虑解决方法,如下所示:

    public foo(Bar bar) {
        if validateBar(bar)
            this.bar = bar;
        else
            throw Exception("Invalid bar passed along to foo");
    }

或:

    public foo(Bar bar) {
        if (!setBar(bar))
            throw Exception("Invalid bar passed along to foo");
    }

你可以看到一些简单的事情是如何很快失去控制的。如果在验证的基础上还要做一些卫生工作,那就更糟糕了

所以我的问题是,如何在保持类结构相对简单的同时处理验证问题

编辑 setbar的第一个例子应该是void,但意外地放了bar,现在更正了


共 (1) 个答案

  1. # 1 楼答案

    以上都没有

    按照惯例,如果实现fluent interface,setter返回void,但可能返回实例的类型(在本例中为Foo,而不是Bar),在这种情况下,setter方法的最后一行是return this;。(您的示例缺少返回,因此无法编译)

    如果setter的参数必须为“valid”,则不应影响返回类型。相反,该方法应该爆炸:

    public void setBar(Bar bar) {
        if (!validateBar(bar)) {
            throw new IllegalArgumentException("Bar is invalid");
        }
        this.bar = bar;
    }
    

    这里不返回布尔值的一个很好的理由是,调用方可能不会检查返回值,并且可能会盲目地继续,好像一切正常,这当然是不好的

    此外,最好通过在Bar构造函数中移动validateBar()的逻辑,抛出一个IllegalArgumentException来避免创建无效的Bar,如果传入的参数将创建一个无效的Bar,那么可以从Foo中删除检查

    如果validateBar()方法是static,这意味着可以在没有Foo上下文的情况下验证Bar,因此逻辑应该在Bar-Foo中实现,如果不需要验证Bar,则它不应该负责或知道如何验证

    但是,如果Foo对一个有效的Bar有特殊的要求,而这个要求不适用于其他地方,那么创建一个Bar的子类,例如FooBar extends Bar,它同样在其构造函数中实现了Foo的特殊验证要求

    如果验证一个Bar确实需要一个Foo的上下文来验证,并且在Foo之间重用Bar实例是不需要的,那么Bar类应该是Foo的一个内部类,在这种情况下,验证仍然可以在条中constructor, and the state of the containingFoo`可根据需要用于验证逻辑

    如果验证一个Bar需要一个Foo的上下文来验证,需要重用Bar实例,那么Bar不能是一个内部类,验证代码应该存在于Foo中,正如您在validateBar(Bar bar)方法中所建议的那样,除非它不是static,否则该方法将使用Foo字段

    也考虑重新命名它^ {CD38>},因为参数的类型使被验证的内容变得清晰。